package com.ddyx.service.impl;

import java.util.HashMap;

import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.baidu.aip.face.AipFace;
import com.ddyx.common.util.ImageIOUtil;
import com.ddyx.model.DetectFaceInfo;
import com.ddyx.model.FaceDetectResult;
import com.ddyx.model.FaceIdentifyResult;
import com.ddyx.model.IdentifyFaceInfo;
import com.ddyx.service.IFaceRecognitionManager;


/**
 * 基于Baidu AI接口实现
 * 
 * @author zhongchzh
 *
 */
public class BaiduFaceRecognitionManager implements IFaceRecognitionManager {

	private static final Logger logger = LoggerFactory.getLogger(BaiduFaceRecognitionManager.class);
	
	private AipFace client;
	
	/**人脸检测扩展参数 */
	private HashMap<String, String> detectOptions;
	
	/** 人脸库管理 */
	private HashMap<String, String> actionOptions;
	
	public BaiduFaceRecognitionManager(String appId, String apiKey, String secretKey) {
		this.client = new AipFace(appId, apiKey, secretKey);
		this.client.setConnectionTimeoutInMillis(1000);
		this.client.setSocketTimeoutInMillis(10000); 
		
		this.detectOptions = new HashMap<String, String>(2);
		//查找图片中的人脸数量
		this.detectOptions.put("max_face_num", "5");
		//设置返回的属性（年龄、性别和质量）
		this.detectOptions.put("face_fields", "age,gender,qualities");
		
		this.actionOptions = new HashMap<String, String>(1);
		this.actionOptions.put("action_type", "append");
	}
	
	@Override
	public FaceDetectResult detectFace(String imagePath) {
		FaceDetectResult detectResult = detectFace(ImageIOUtil.getImageBinary(imagePath));
		return detectResult;
	}
	
	@Override
	public FaceDetectResult detectFace(byte[] imageData) {
		JSONObject result = client.detect(imageData, this.detectOptions);
		FaceDetectResult detectResult = parseFaceDetectResultFromJson(result);
		return detectResult;
	}
	
	/**
	 * 从JSON解析出人脸检测结果
	 * 
	 * @param resp
	 * @return
	 */
	private FaceDetectResult parseFaceDetectResultFromJson(JSONObject result) {
		if(result.has("result_num")) {
			int result_num = result.getInt("result_num");
			if(result_num > 0) {
				FaceDetectResult detectResult = new FaceDetectResult();
				JSONArray results = result.getJSONArray("result");
				for(int i=0;i<result_num;i++) {
					JSONObject singleResult = results.getJSONObject(i);
					int top = singleResult.getJSONObject("location").getInt("top");
					int left = singleResult.getJSONObject("location").getInt("left");
					int width = singleResult.getJSONObject("location").getInt("width");
					int height = singleResult.getJSONObject("location").getInt("height");
					
					DetectFaceInfo faceInfo = new DetectFaceInfo();
					faceInfo.setX(left);
					faceInfo.setY(top);
					faceInfo.setWidth(width);
					faceInfo.setHeight(height);
					
					faceInfo.setFaceProbability(singleResult.getInt("face_probability"));
					
					String gender = singleResult.getString("gender");
					if(StringUtils.hasText(gender)) {
						if("male".equalsIgnoreCase(gender))
							faceInfo.setGender(1);
						else if("female".equalsIgnoreCase(gender))
							faceInfo.setGender(0);
					}

					double age = singleResult.getDouble("age");
					faceInfo.setAge((int)age);
					
					faceInfo.setYawAngle(singleResult.getDouble("yaw"));
					faceInfo.setPitchAngle(singleResult.getDouble("pitch"));
					faceInfo.setRollAngle(singleResult.getDouble("roll"));
					
					if(singleResult.has("qualities")) {
						JSONObject qualitiesResult = singleResult.getJSONObject("qualities");
						if(qualitiesResult.has("blur")) {
							faceInfo.setBlur(qualitiesResult.getDouble("blur"));
						}
						if(qualitiesResult.has("illumination")) {
							faceInfo.setIllumination(qualitiesResult.getInt("illumination"));
						}
					}
					
					if(faceInfo.isValid()) {
						detectResult.addFaceInfo(faceInfo);
					}
				}
				return detectResult;
			}
		} else {
			long error_code = result.getLong("error_code");
			String error_msg = result.getString("error_msg");
			logger.error("人脸检测错误，错误码：{}，错误描述：{}", error_code, error_msg);
		}
		return null;
	}
	
	/**
	 * 从原始图获取里获取脸图数据
	 * @param detectResult
	 */
	/*private void getFaceImageFromOriginalImage(String imagePath, FaceDetectResult detectResult) {
		Iterator<DetectFaceInfo> iter = detectResult.getResultList().iterator();
		while(iter.hasNext()) {
			DetectFaceInfo faceInfo = iter.next();
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			try {
				BufferedImage faceImage = null;
				String prefix = imagePath.substring(0, 4);
				if("http".equalsIgnoreCase(prefix)) {
					faceImage = Thumbnails.of(new URL(imagePath)).sourceRegion(faceInfo.getX(), faceInfo.getY(), faceInfo.getWidth(), faceInfo.getHeight())
							.size(100, 100).keepAspectRatio(false).asBufferedImage();
				} else {
					faceImage = Thumbnails.of(imagePath).sourceRegion(faceInfo.getX(), faceInfo.getY(), faceInfo.getWidth(), faceInfo.getHeight())
							.size(100, 100).keepAspectRatio(false).asBufferedImage();
				}
				ImageIO.write(faceImage, "jpg", bos);
	    			bos.flush();
	    			faceInfo.setFaceImageData(bos.toByteArray());
			} catch(Exception err) {
				iter.remove();
			} finally {
				try {
					bos.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}*/

	@Override
	public void addFace(String userId, String userName, String groupId, String encodedImage, boolean replace) {
		if(replace) {
			this.actionOptions.put("action_type", "replace");
		} else {
			this.actionOptions.put("action_type", "append");
		}
		this.client.addUser(userId, userName, groupId, encodedImage, this.actionOptions);
	}

	@Override
	public void addFace(String userId, String userName, String groupId, byte[] imageData, boolean replace) {
		if(replace) {
			this.actionOptions.put("action_type", "replace");
		} else {
			this.actionOptions.put("action_type", "append");
		}
		this.client.addUser(userId, userName, groupId, imageData, this.actionOptions);
	}

	@Override
	public FaceIdentifyResult identifyFace(String encodedImage, String groupId) {
		JSONObject result = client.identifyUser(groupId, encodedImage, null);
		return parseFaceIdentifyResultFromJson(result);
	}
	
	@Override
	public FaceIdentifyResult identifyFace(byte[] imageData, String groupId) {
		JSONObject result = client.identifyUser(groupId, imageData, null);
		return parseFaceIdentifyResultFromJson(result);
	}
	
	/**
	 * 从JSON解析出人脸查找结果
	 * 
	 * @param result
	 * @return
	 */
	private FaceIdentifyResult parseFaceIdentifyResultFromJson(JSONObject result) {
		if(result.has("result_num")) {
			int result_num = result.getInt("result_num");
			if(result_num > 0) {
				FaceIdentifyResult identifyResult = new FaceIdentifyResult();
				JSONArray results = result.getJSONArray("result");
				for(int i=0;i<result_num;i++) {
					JSONObject singleResult = results.getJSONObject(i);
					String group_id = singleResult.getString("group_id");
					String user_id = singleResult.getString("uid");
					String user_info = singleResult.getString("user_info");
					JSONArray scores = singleResult.getJSONArray("scores");
					double score = scores.getDouble(0);
					if(score > 80) {
						IdentifyFaceInfo userFaceInfo = new IdentifyFaceInfo();
						userFaceInfo.setGroupId(group_id);
						userFaceInfo.setUserId(user_id);
						userFaceInfo.setUserName(user_info);
						userFaceInfo.setScore(score);
						identifyResult.addUserFaceInfo(userFaceInfo);
					}
				}
				return identifyResult;
			}
		} else {
			int error_code = result.getInt("error_code");
			String error_msg = result.getString("error_msg");
			logger.error("人脸查找错误，错误码：{}，错误描述：{}", error_code, error_msg);
		}
		return null;
	}

	
}
